#include "etc/network/networkconfig.h"

// 格式化输出 - 
void createFormat(char *buffer, char value, int len) {
    if (len <= 0) len = 0;
    memset(buffer, value, len);
}

void config_property_iterator(gpointer item, gpointer prefix) {
    char buffer[100] = {0};
    createFormat(buffer, ' ', 21-strlen(((ConfigInterfaceProperty*)item)->key));
    printf("%s %s %s %s\n", ((ConfigInterfaceProperty*)item)->key, buffer, (char*)prefix, ((ConfigInterfaceProperty*)item)->value);
}

// 复制属性
ConfigInterfaceProperty *createConfigInterfacePropertyCopy(const ConfigInterfaceProperty *const_property) {
    if (const_property == NULL) return NULL;

    ConfigInterfaceProperty *property = g_new0(ConfigInterfaceProperty, 1);
    strcpy(property->key, const_property->key);
    strcpy(property->value, const_property->value);

    return property;
}

// 复制接口状态
ConfigInterface * createConfigInterfaceCopy(const ConfigInterface *const_interface) {
    if (const_interface == NULL) return NULL;

    ConfigInterface *interface = g_new0(ConfigInterface, 1);
    interface->isAuto = const_interface->isAuto;
    strcpy(interface->iface, const_interface->iface);
    strcpy(interface->ipType, const_interface->ipType);
    strcpy(interface->workType, const_interface->workType);
    
    if (const_interface->properties != NULL) {
        GSList *iter = NULL;
        for (iter = const_interface->properties; iter; iter = iter->next) {
            interface->properties = g_slist_append(interface->properties, createConfigInterfacePropertyCopy(iter->data));
        }
    }
    return interface;
}

bool setConfigInterface(ConfigInterface *interface, 
                        bool isauto, char iface[100], 
                        char iptype[100], char worktype[100], 
                        GSList *properties) {
    interface->isAuto = isauto;
    strcpy(interface->iface, iface);
    strcpy(interface->ipType, iptype);
    strcpy(interface->workType, worktype);
    interface->properties = properties;

    return true;
}
// ------------------------------------ Config File Low Api
static bool writeConfig(FILE *fp, const char *iface, const bool isAuto, const char *ipv4, const char *type, const GSList *properties) {
    char autoIface[100] = {0};
    char interface[100] = {0};

    sprintf(autoIface, "auto %s", iface);
    sprintf(interface, "iface %s %s %s", iface, ipv4, type);
    if (isAuto) {
        fputs(autoIface, fp);
        fputc('\n', fp);
    }

    fputs(interface, fp);
    fputc('\n', fp);

    for (GSList *iter = (GSList*)properties; iter; iter = iter->next) {
        ConfigInterfaceProperty *p = (ConfigInterfaceProperty*)iter->data;
        char property[100] = {0};
        sprintf(property, "        %s %s", (char*)p->key, (char*)p->value);
        fputs(property, fp);
        fputc('\n', fp);
    }
    fputc('\n', fp);

    return true;
}
static bool writeConfigInterface(FILE *fp, const ConfigInterface *interface) {
    return writeConfig(fp, interface->iface, interface->isAuto, interface->ipType, interface->workType, interface->properties);
}

// ------------------------------------ Wrap

bool NetworkConfigExists(const char *path) {
    return FileExists(path);
}

bool NetworkConfigInterfaceNames(const char *path, GSList **list) {
    *list = NULL;
    if (!NetworkConfigExists(path)) return false;

    FILE *fp;
    fp = fopen(path, "r");
    bool eof = false;
    while (!eof)
    {
        char buffer[100] = {0};
        eof = freadline(fp, buffer);
        if (eof) continue;

        if (LineHasValue(buffer, "iface") && LineStartWith(buffer, "iface")) {
            *list = g_slist_append(*list, g_slist_nth(split(buffer, ' '), 1)->data);
        }
    }
    fclose(fp);

    return true;
}

bool NetworkConfigInterfaceAutoNames(const char *path, GSList **list) {
    *list = NULL;
    if (!NetworkConfigExists(path)) return false;

    FILE *fp;
    fp = fopen(path, "r");
    bool eof = false;
    while (!eof)
    {
        char buffer[100] = {0};
        eof = freadline(fp, buffer);
        if (eof) continue;
        if (LineHasValue(buffer, "auto") && LineStartWith(buffer, "auto")) {
            *list = g_slist_append(*list, g_slist_nth(split(buffer, ' '), 1)->data);
        }
    }
    fclose(fp);
    
    return true;
}

bool NetworkConfigInterfaceExists(const char *path, const char *iface) {
    if (!NetworkConfigExists(path)) return false;
    if (isNull(iface)) return false;

    FILE *fp;
    fp = fopen(path, "r");
    bool eof = false;
    while (!eof)
    {
        char buffer[100] = {0};
        eof = freadline(fp, buffer);
        if (eof) continue;

        if (LineHasValue(buffer, "iface") && LineHasValue(buffer, iface) && LineStartWith(buffer, "iface")) {
            GSList *splitT = split(buffer, ' ');
            bool same = false; // 相同
            if (g_slist_length(splitT) > 2) {
                same = LineEqual(g_slist_nth(splitT, 1)->data, iface);
            }
            GS_FREE_ALL_CLEAN(splitT)
            if (same) {
                fclose(fp);
                return true;
            }
        }
    }
    fclose(fp);

    return false;
}

bool NetworkConfigInterfaceIsAuto(const char *path, char *iface) {
    if (!NetworkConfigInterfaceExists(path, iface)) return false;

    FILE *fp;
    fp = fopen(path, "r");
    bool eof = false;
    while (!eof)
    {
        char buffer[100] = {0};
        eof = freadline(fp, buffer);
        if (eof) continue;

        if (LineHasValue(buffer, "auto") && LineStartWith(buffer, "auto")) {
            GSList *splitT = split(buffer, ' ');
            bool same = false; // 相同
            if (g_slist_length(splitT) >= 1) {
                same = LineEqual(g_slist_nth(splitT, 1)->data, iface);
            }
            GS_FREE_ALL_CLEAN(splitT)
            if (same) {
                fclose(fp);
                return same;
            }
        }
    }
    fclose(fp);

    return false;
}

bool NetworkConfigInterfaceDetails(const char *path, char *iface, GSList **list) {
    *list = NULL;
    if (!NetworkConfigExists(path)) return false;

    FILE *fp;
    fp = fopen(path, "r");
    bool eof = false;
    while (!eof)
    {
        char buffer[100] = {0};
        eof = freadline(fp, buffer);
        if (eof) continue;

        if (LineHasValue(buffer, "iface") && LineStartWith(buffer, "iface")) {
            char ifaceDetail[100] = {0};
            if(!LineTrim_buf(buffer, ifaceDetail)) continue;

            GSList *temp = split(ifaceDetail, ' ');

            if (strcmp(iface, (char*)g_slist_nth(temp, 1)->data) == 0) {
                *list = temp;
                break;
            }
            g_slist_foreach(temp, (GFunc)g_free, NULL);
            g_slist_free(temp);
        }
    }
    fclose(fp);

    return true;
}

bool NetworkConfigsWithPath(const char *path, GSList **list) {
    if (!NetworkConfigExists(path)) return false;
    
    GSList *ifaces = NULL;
    if (NetworkConfigInterfaceNames(path, &ifaces)) {
        for (GSList *iter = ifaces; iter; iter = iter->next) {

            ConfigInterface *interface = g_new0(ConfigInterface, 1);
            *list = g_slist_append(*list, interface);

            if(NetworkConfigInterface(path, iter->data, interface)) {
                NetworkConfigInterfaceSectionProperties(path, iter->data, &interface->properties);
            }
        }
    }
    return true;
}




// ------------------------------------ Network Config: ConfigInterface / ConfigInterfaceProperty

// 寻找配置文件中接口的配置状态信息
bool NetworkConfigInterface(const char *path, char *iface, ConfigInterface *interface) {
    if (!NetworkConfigExists(path)) return false;

    GSList *detailed = NULL;
    // ConfigInterface *interface = g_new0(ConfigInterface, 1);

    // 如果是Auto，将设置为Auto
    if (NetworkConfigInterfaceIsAuto(path, iface)) interface->isAuto = true;
    
    // 设置其它信息
    if (NetworkConfigInterfaceDetails(path, iface, &detailed)) {
        if (g_slist_length(detailed) == 4) {
            strcpy(interface->iface, (char*)g_slist_nth(detailed, 1)->data);
            strcpy(interface->ipType, (char*)g_slist_nth(detailed, 2)->data);
            strcpy(interface->workType, (char*)g_slist_nth(detailed, 3)->data);
        }
        g_slist_foreach(detailed, (GFunc)g_free, NULL);
        g_slist_free(detailed);
    }

    return true;
}

// 获取配置文件的中指定接口节点的属性
bool NetworkConfigInterfaceSectionProperties(const char *path, char *section, GSList **list) {
    *list = NULL;
    if (!NetworkConfigExists(path)) return false;

    FILE *fp;
    fp = fopen(path, "r");
    bool eof = false;
    bool isSection = false;
    while (!eof)
    {
        char buffer[200] = {0};
        eof = freadline(fp, buffer);
        if (eof) continue;
        if (!isSection && LineStartWith(buffer, "iface") && LineHasValue(buffer, section)) {
            GSList *temp = split_cnt(buffer, ' ', 2);
            if (g_slist_length(temp) >= 2 && strcmp(g_slist_nth(temp, 1)->data, section) == 0) {
                // g_slist_foreach(temp, (GFunc)printf_iterator, ">>>");
                isSection = true;
            }
            GS_FREE_ALL_CLEAN(temp)
            continue;
        }
        if (isSection && LineStartWith(buffer, "iface") && !LineStartWith(buffer, " ")) {
            isSection = false;
            continue;
        }
        if (!LineStartWith(buffer, " ")) continue;
        if (!isSection) continue;
        char *buf = LineTrim(buffer);
        if (buf != NULL){
            ConfigInterfaceProperty *p = g_new0(ConfigInterfaceProperty, 1);
            GSList *temp = split_cnt(buf, ' ', 1);
            free(buf);

            strcpy(p->key, (char*)g_slist_nth(temp, 0)->data);
            if (g_slist_length(temp) >= 2) {
                strcpy(p->value, (char*)g_slist_nth(temp, 1)->data);
            } else {
                
            }

            GS_FREE_ALL_CLEAN(temp)

            *list = g_slist_append(*list, p);
        }
    }
    fclose(fp);
    // printf("%s - 出去\n", __FUNCTION__);
    return true;
}



// Network Config: Write to File(Save Config)
bool NetworkConfigInterfaceWriter(const char *path, const GSList *interfaces) {
    if (interfaces == NULL) return false;
    if (!NetworkConfigExists(path)) return false;

    GSList *iter = (GSList*)interfaces;

    FILE *fp = NULL;
    if (g_slist_length(iter)>0) {
        fp = fopen(path, "w");
    }

    for (; iter; iter = iter->next) {
        GSList *properties = NULL;
        ConfigInterface *interface = NULL;

        interface = iter->data;
        properties = interface->properties;

        writeConfigInterface(fp, interface);
    }

    fclose(fp);
    return true;
}

// ------------------------------------ Network Config: Append

// 在配置文件中追加一个接口 - 接口可能含属性
bool NetworkConfigAppendConfigInterface(const char *path, ConfigInterface *interface) {
    if (!NetworkConfigExists(path)) return false;

    FILE *fp = NULL;
    fp = fopen(path, "a+");

    writeConfigInterface(fp, interface);

    fclose(fp);
    return true;
}

// 在配置文件中追加多个接口 - 接口可能含属性
bool NetworkConfigAppendConfigInterfaces(const char *path, GSList *interfaces) {
    if (!NetworkConfigExists(path)) return false;
    
    for (GSList *iter = interfaces; iter; iter = iter->next) {
        if (!NetworkConfigAppendConfigInterface(path, (ConfigInterface*)iter->data)) return false;
    }

    return true;
}

// ------------------------------------ Network Config: Modify

// 在配置文件中修改一个接口信息
bool NetworkConfigModifyConfigInterface(const char *path, const ConfigInterface *modify_interface) {
    if (!NetworkConfigExists(path)) return false;

    GSList *interfaces = NULL;

    if (NetworkConfigsWithPath(path, &interfaces)) {
        FILE *fp = fopen(path, "w");
        for (GSList *iter = interfaces; iter; iter = iter->next) {
            // 匹配-使用变更节点-继续
            if (LineEqual(((ConfigInterface*)iter->data)->iface, (char*)modify_interface->iface)) {
                writeConfigInterface(fp, modify_interface);
                continue;
            }
            writeConfigInterface(fp, iter->data);

            NC_CIP_FREE_ALL_CLEAN(iter->data)
        }
        fclose(fp);
    }
    
    NC_CIS_FREE_ALL_CLEAN(interfaces)
    return true;
}

// ------------------------------------ Network Config: Insert
bool NetworkConfigInsertConfigInterface(const char *path, const ConfigInterface *interface) {
    if (!NetworkConfigExists(path)) return false;

    if (NetworkConfigInterfaceExists(path, (char*)interface->iface)) {
        INFO_LOG("接口(%s)已存在",interface->iface);
        return false;
    }

    GSList *interfaces = NULL;

    if(NetworkConfigsWithPath(path, &interfaces)) {
        interfaces = g_slist_append(interfaces, createConfigInterfaceCopy(interface));
        
        FILE *fp = fopen(path, "w");
        for (GSList *iter = interfaces; iter; iter = iter->next) {
            writeConfigInterface(fp, iter->data);
            GS_FREE_ALL_CLEAN(((ConfigInterface*)iter->data)->properties);
        }
        fclose(fp);
    }

    NC_CIS_FREE_ALL_CLEAN(interfaces)
    return true;
}

// ------------------------------------ Network Config: Remove
bool NetworkConfigRemoveConfigInterface(const char *path , const char *iface){
    if (!NetworkConfigExists(path)) return false;
    if (!NetworkConfigInterfaceExists(path, iface)) {
        DEBUG_LOG("%s 接口不存在", iface);
        return false;
    }

    GSList *interfaces = NULL;

    if(NetworkConfigsWithPath(path, &interfaces)) {
        FILE *fp = fopen(path, "w");
        for (GSList *iter = interfaces; iter; iter = iter->next) {
            if (LineEqual(((ConfigInterface*)iter->data)->iface, iface)) continue; 
            writeConfigInterface(fp, iter->data);
            GS_FREE_ALL_CLEAN(((ConfigInterface*)iter->data)->properties);
        }
        fclose(fp);
    }

    NC_CIS_FREE_ALL_CLEAN(interfaces);
    return true;
}
